package com.gitee.taotaojs.util.comparator;

import com.gitee.taotaojs.util.CollectionUtil;
import com.gitee.taotaojs.util.reflect.ReflectUtil;
import lombok.Builder;
import lombok.Data;

import java.lang.reflect.Field;
import java.text.Collator;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
 * @author TaoTaojs
 * @date 2019/4/8 11:54
 * <p>Description</p>
 * <h1>对象排序工具类</h1>
 * <h2>简介</h2>
 * 用于复杂对象的多条件排序，类似SQL中的order by
 * <h3>主要功能：</h3>
 * <ol>
 *     <li>支持对于指定属性名进行排序</li>
 *     <li>字符串类型将默认使用中文排序方式进行排序</li>
 *     <li>支持数组与集合两种方式进行排序的操作</li>
 * </ol>
 *
 * <h3>使用数组方式进行排序</h3>
 * String[] sortBy = new String[] { "name", "post" };
 * int orderBy = 1;//1:升序，-1：降序
 * MyComparator myCmp = new MyComparator(sortBy, orderBy);
 * Collections.sort(list, myCmp);
 * <h3>使用集合方式进行排序</h3>
 * List comparatorList = new ArrayList();
 * comparatorList.add(ComparatorBean.Builder.build())
 * MyComparator myCmp = new MyComparator(comparatorList);
 * Collections.sort(list, myCmp);
 * 关联类:
 * History:
 * <author>        <time>                      <version>          <desc>
 * TaoTaojs        2020/4/22 1:37 PM           V1.0               增加空，非空，非空白三种判断方法
 */
public class MyComparator<T> implements Comparator<T> {

    /** 默认使用中文对集合进行排序 */
    private Comparator<Object> cmp = Collator.getInstance(java.util.Locale.CHINA);

    /** 判断字段优先级 */
    private String[] sortBy;

    /** 升序 -> -1  降序 -> 1 */
    private int order;

    /** 排序配置集合 */
    private List<ComparatorBean> comparatorBeanList;

    public MyComparator(String[] sortBy, int order) {
        this.sortBy = sortBy.clone();
        this.order = order;
    }

    public MyComparator(List<String> sortBy, int order) {
        this.sortBy = sortBy.toArray(new String[0]);
        this.order = order;
    }

    public MyComparator(List<ComparatorBean> comparatorBeanList){
        this.comparatorBeanList = comparatorBeanList;
    }

    public MyComparator(Class clazz){
        this.comparatorBeanList = comparatorBeanList;
    }

    /**
     * 定义排序规则 如果按照不止一个属性进行排序 这按照属性的顺序进行排序,类似sql order by 即只要比较出同位置的属性就停止
     */
    @Override
    public int compare(T o1, T o2) {
        int compareResult = 0;
        if(CollectionUtil.isNotEmpty(sortBy)){
            //如果对象数组不为空
            for (int i = 0; i < sortBy.length; i++) {
                Object value1 = ReflectUtil.invokeGet(o1, sortBy[i]);
                Object value2 = ReflectUtil.invokeGet(o2, sortBy[i]);
                compareResult = compareOriginal(value1, value2);
                if(compareResult != 0){
                    return compareResult;
                }
            }
        }else if(CollectionUtil.isNotEmpty(comparatorBeanList)){
            //如果对象+排序集合不为空
            for (ComparatorBean comparatorBean : comparatorBeanList) {
                Object value1 = ReflectUtil.invokeGet(o1, comparatorBean.getProName());
                Object value2 = ReflectUtil.invokeGet(o2, comparatorBean.getProName());
                compareResult = compareOriginal(value1, value2, comparatorBean.getOrder());
                if(compareResult != 0){
                    return compareResult;
                }
            }
        }

        return 0;
    }

    private int compareOriginal(Object obj1, Object obj2){
        return compareOriginal(obj1, obj2, this.order);
    }
    private int compareOriginal(Object obj1, Object obj2, int order){
        int compareResult = 0;
        if (obj1 instanceof Integer && obj2 instanceof Integer) {
            //如果两个全都是Integer类型
            int v1 = Integer.parseInt(obj1.toString());
            int v2 = Integer.parseInt(obj2.toString());
            if (v1 > v2) {
                compareResult = 1 * order;
            } else if (v1 < v2) {
                compareResult = -1 * order;
            }
        } else {
            //如果两个是类似String的类型，则使用cmp排序
            int result = cmp.compare(obj1, obj2);
            if (result != 0) {
                compareResult = result * order;
            }
        }
        //如果两个相等
        return compareResult;
    }

    /**
     * 直接使用此方法可进行排序
     * @param sortBy 排序的字段优先级
     * @param orderBy 1:升序，-1：降序
     * @param list 需要被排序的集合
     * @param <T> 泛型
     */
    public static<T> void sort(List<String> sortBy, Integer orderBy, List<T> list){
        MyComparator<T> myCmp = new MyComparator<>(sortBy, orderBy);
        Collections.sort(list, myCmp);
    }
    @SuppressWarnings("checkstyle:MissingJavadocMethod")
    public static<T> void sort(String[] sortBy, Integer orderBy, List<T> list){
        MyComparator<T> myCmp = new MyComparator<>(sortBy, orderBy);
        Collections.sort(list, myCmp);
    }
    @SuppressWarnings("checkstyle:MissingJavadocMethod")
    public static<T> void sort(List<T> list, Class<T> clazz){
        MyComparator<T> myCmp = new MyComparator<>(clazz);
        Collections.sort(list, myCmp);
    }

    /**
     * 用于排序的属性类类型
     */
    @Data
    @Builder
    public static class ComparatorBean {

        /** 属性名称 */
        private String proName;
        /** 升序或降序， 1升序，0降序 */
        @Builder.Default
        private int order = 1;
    }

    public static void getAnnotationConfiguration(Class clazz) throws ClassNotFoundException {
        Field[] classFields = clazz.getDeclaredFields();

        for (Field field : classFields) {
            Order myOrder = field.getAnnotation(Order.class);
            DescOrder descOrder = field.getAnnotation(DescOrder.class);
            System.out.println(field);
            System.out.println(myOrder + "" + descOrder);
            //TODO 基于注解的排序，未完成
        }

    }


}
